package com.huirui.server.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huirui.server.constant.CouponConstant;
import com.huirui.server.constant.CouponStatus;
import com.huirui.server.constant.CouponUseStatus;
import com.huirui.server.context.UserContext;
import com.huirui.server.exception.CouponExistsException;
import com.huirui.server.mapper.CouponUserMapper;
import com.huirui.server.pojo.entity.Coupon;
import com.huirui.server.pojo.entity.CouponUser;
import com.huirui.server.pojo.vo.CouponVo;
import com.huirui.server.pojo.vo.UserCouponListVo;
import com.huirui.server.service.CouponService;
import com.huirui.server.service.CouponUserService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author yujun
 * @description 针对表【t_coupon_user(用户优惠券领取记录表)】的数据库操作Service实现
 * @createDate 2025-10-28 22:32:43
 */
@Service
public class CouponUserServiceImpl extends ServiceImpl<CouponUserMapper, CouponUser>
        implements CouponUserService {

    @Resource
    private CouponService couponService;


    @Override
    public List<CouponVo> listMallCoupon(Integer type) {
        List<Coupon> couponList = couponService
                .lambdaQuery()
                .select(
                        Coupon::getId,
                        Coupon::getName,
                        Coupon::getCouponType,
                        Coupon::getDenomination,
                        Coupon::getHasThreshold,
                        Coupon::getThreshold,
                        Coupon::getExpiryType,
                        Coupon::getValidDays,
                        Coupon::getAvailableStartTime,
                        Coupon::getAvailableEndTime,
                        Coupon::getHasQuantityLimit,
                        Coupon::getQuantityLimit,
                        Coupon::getDistributedQuantity,
                        Coupon::getUserMaxCollectionLimit
                )
                .eq(Coupon::getCouponType, type)
                .eq(Coupon::getCouponStatus, CouponStatus.NORMAL)
                .le(Coupon::getDistributionStartTime, LocalDateTime.now())
                .ge(Coupon::getDistributionEndTime, LocalDateTime.now())
                .orderByDesc(Coupon::getCreateTime)
                .list();
        // 用户的优惠券每个拥有多少个
        List<CouponUser> userCouponList = lambdaQuery().eq(CouponUser::getUserId, UserContext.getId()).list();
        Map<Long, Long> countMap = new HashMap<>();
        if (userCouponList != null && !userCouponList.isEmpty()) {
            userCouponList.forEach(userCoupon -> {
                Long couponId = userCoupon.getCouponId();
                if (countMap.containsKey(couponId)) {
                    countMap.put(couponId, countMap.get(couponId) + 1);
                } else {
                    countMap.put(couponId, 1L);
                }
            });
        }
        List<CouponVo> couponVoList = new ArrayList<>();
        for (Coupon coupon : couponList) {
            CouponVo couponVo = new CouponVo();
            couponVo.setId(coupon.getId());
            couponVo.setName(coupon.getName());
            couponVo.setCouponType(coupon.getCouponType());
            couponVo.setDenomination(coupon.getDenomination());
            couponVo.setHasThreshold(coupon.getHasThreshold());
            couponVo.setThreshold(coupon.getThreshold());
            // 优惠券数量的判断
            Long userMaxClaimedQuantity = Long.valueOf(coupon.getUserMaxCollectionLimit());
            Long userClaimedQuantity = countMap.getOrDefault(coupon.getId(), 0L);
            if (coupon.getHasQuantityLimit() == CouponConstant.HAS_QUANTITY_LIMIT && coupon.getDistributedQuantity() >= coupon.getQuantityLimit()) {
                couponVo.setCouponStatus(CouponStatus.CLAIMED_OUT);
            } else if (userClaimedQuantity >= userMaxClaimedQuantity) {
                couponVo.setCouponStatus(CouponStatus.CLAIMED);
            } else {
                couponVo.setCouponStatus(CouponStatus.UNCLAIMED);
            }
            couponVo.setExpiryType(coupon.getExpiryType());
            if (couponVo.getExpiryType() == CouponConstant.EXPIRE_DAYS) {
                couponVo.setValidDays(coupon.getValidDays());
            } else if (couponVo.getExpiryType() == CouponConstant.EXPIRE_RANGE) {
                couponVo.setAvailableStartTime(coupon.getAvailableStartTime());
                couponVo.setAvailableEndTime(coupon.getAvailableEndTime());
            }
            couponVoList.add(couponVo);
        }
        return couponVoList;
    }

    @Override
    public void addUserCoupon(Long couponId) {
        Long userId = UserContext.getId();
        // 首先判断优惠券是否存在
        boolean exists = couponService
                .lambdaQuery()
                .eq(Coupon::getId, couponId)
                .eq(Coupon::getCouponStatus, CouponStatus.NORMAL)
                .exists();
        if (!exists) {
            throw new CouponExistsException("优惠券不存在");
        }
        Coupon coupon = couponService
                .lambdaQuery()
                .select(
                        Coupon::getId,
                        Coupon::getName,
                        Coupon::getCouponType,
                        Coupon::getDenomination,
                        Coupon::getHasThreshold,
                        Coupon::getThreshold,
                        Coupon::getExpiryType,
                        Coupon::getValidDays,
                        Coupon::getAvailableStartTime,
                        Coupon::getAvailableEndTime,
                        Coupon::getHasQuantityLimit,
                        Coupon::getQuantityLimit,
                        Coupon::getDistributedQuantity,
                        Coupon::getUserMaxCollectionLimit
                )
                .eq(Coupon::getId, couponId)
                .eq(Coupon::getCouponStatus, CouponStatus.NORMAL)
                .one();
        Long count = lambdaQuery()
                .eq(CouponUser::getUserId, userId)
                .eq(CouponUser::getCouponId, couponId)
                .count();
        if (count > coupon.getUserMaxCollectionLimit()) {
            throw new CouponExistsException("优惠券领取已达到最大限制！");
        }
        // 判断是否还有库存
        if (coupon.getHasQuantityLimit() == CouponConstant.HAS_QUANTITY_LIMIT && coupon.getDistributedQuantity() > coupon.getQuantityLimit()) {
            throw new CouponExistsException("优惠券已被领完！");
        }
        CouponUser couponUser = new CouponUser();
        couponUser.setUserId(userId);
        couponUser.setCouponId(couponId);
        couponUser.setGetTime(LocalDateTime.now());
        couponUser.setUseStatus(CouponUseStatus.UNUSED);
        couponUser.setCreateTime(LocalDateTime.now());
        // 设置过期时间
        if (coupon.getExpiryType() == CouponConstant.EXPIRE_DAYS) {
            couponUser.setAvailableStartTime(LocalDateTime.now());
            couponUser.setAvailableEndTime(LocalDateTime.now().plusDays(coupon.getValidDays()));
        } else if (coupon.getExpiryType() == CouponConstant.EXPIRE_RANGE) {
            couponUser.setAvailableStartTime(coupon.getAvailableStartTime());
            couponUser.setAvailableEndTime(coupon.getAvailableEndTime());
        }
        save(couponUser);
    }

    @Override
    public UserCouponListVo listUserCouponByType(Integer type) {
        // 查询用户的优惠券，包含正常，过期，关闭的优惠券
        // 已关闭的优惠券不可以继续领取，但是可以继续使用
        UserCouponListVo res = new UserCouponListVo();
        Long userId = UserContext.getId();
        Long unusedCouponNumber = baseMapper.getUserUnusedCouponNumber(userId);
        Long usedCouponNumber = baseMapper.getUserUsedCouponNumber(userId);
        Long invalidCouponNumber = baseMapper.getUserInvalidCouponNumber(userId);
        res.setUsedNumber(usedCouponNumber);
        res.setInvalidNumber(invalidCouponNumber);
        res.setUnusedNumber(unusedCouponNumber);
        List<CouponVo> userCouponList = null;
        if (type == CouponUseStatus.UNUSED) {
            userCouponList = baseMapper.listUserNormalCoupon(userId);
        } else if (type == CouponUseStatus.USED) {
            userCouponList = baseMapper.listUserUsedCoupon(userId);
        } else if (type == CouponUseStatus.EXPIRED) {
            userCouponList = baseMapper.listUserInvalidCoupon(userId);
        }
        res.setUserCouponList(userCouponList);
        return res;
    }
}




